/**
 * Copyright (c) 2019 Coder_League(码农联盟)
 * All rights reserved.
 *
 * File：CommonUtil.java
 * History:
 *         2019年5月11日: Initially created, Liangjing.
 */
package club.coderleague.ilsp.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import club.coderleague.ilsp.common.domain.beans.UploadFile;

/**
 * 公共工具类
 * @author Liangjing
 */
public class CommonUtil {
	
	/**
	 * 判断对象是否为空
	 * @author Liangjing 2019年5月11日
	 * @param <T>
	 * @param obj
	 * @return
	 */
	public static <T> boolean isEmpty(T obj) {
		if(obj instanceof String) {
			return obj != null && !"".equals(obj) ? false : true;
		}else if(obj instanceof List<?>) {
			return obj != null && ((List<?>)obj).size() != 0 ? false : true;
		}else if(obj instanceof Map<?, ?>) {
			return obj != null && !((Map<?, ?>)obj).isEmpty() ? false : true;
		}else {
			return obj != null ? false : true;
		}
	}
	
	/**
	 * 转List<Long>
	 * @author Liangjing 2019年5月17日
	 * @param entityids
	 * @return
	 */
	public static List<Long> toLongArrays(String entityids) {
		List<Long> list = new ArrayList<Long>();
		if(!CommonUtil.isEmpty(entityids)) {
			for (String entityid : entityids.split(",")) {
				list.add(Long.valueOf(entityid));
			}
		}
		return list;
	}
	
	/**
	 * json转对象
	 * @author Liangjing 2019年5月24日
	 * @param <T>
	 * @param json
	 * @param type
	 * @return
	 */
	public static <T> T jsonToObj(String json, Class<T> clazz) {
		if(CommonUtil.isEmpty(json)) {
			return null;
		}
		ObjectMapper mapper = new ObjectMapper();
		try {
			mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			return mapper.readValue(json, clazz);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * json转List
	 * @author Liangjing 2019年6月8日
	 * @param <T>
	 * @param json
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> jsonToList(String json, Class<?> clazz) throws Exception{
		if(CommonUtil.isEmpty(json)) {
			return null;
		}
		ObjectMapper mapper = new ObjectMapper();
		try {
			JavaType type = mapper.getTypeFactory().constructParametricType(List.class, clazz);
			return mapper.readValue(json, type);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 上传文件。
	 * @author Liangjing 2019年5月21日
	 * @param files 文件数据。
	 * @param saveRoot 上传目录。
	 * @param limitTypes 类型。
	 * @param limitSize 大小。
	 * @param datePath 是否生成年月日文件名。
	 * @return
	 * @throws Exception  抛出上传异常。
	 */
	public static List<UploadFile> saveFiles(List<MultipartFile> files, String saveRoot, String limitTypes, long limitSize, boolean datePath) throws Exception {
		List<UploadFile> ufs = new ArrayList<UploadFile>();
		UploadFile uf = null;
		for (MultipartFile fi : files) {
			String name = fi.getOriginalFilename();
			if (name == null || "".equals(name)) continue;

			String fname = name.substring(name.lastIndexOf("\\") + 1);
			String ftype = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
			if (limitTypes.indexOf(ftype) == -1 || fi.getSize() > limitSize) throw new Exception("Type not permitted or too big.");
			String dpath = datePath ? new SimpleDateFormat("/yyyy/MM/dd").format(new Date()) : ""; // 生成年月日文件夹。
			String sname = UUID.randomUUID().toString() + "." + ftype; // 附件名转换。
			String spath = dpath + "/" + sname;
			String ppath = saveRoot + spath;
			File file = new File(saveRoot + dpath);
			// 检查是否存在, 不存在则创建目录。
	        if(!file.exists()) file.mkdirs();
	        // 生成文件。
            fi.transferTo(new File(ppath));
	        
			uf = new UploadFile(spath, fname);
			ufs.add(uf);
		}

		return ufs;
	}
	/**
	 * 上传系统配置文件
	 * @author Liangjing 2019年8月8日
	 * @param files 文件数据。
	 * @param saveRoot 上传目录。
	 * @throws Exception
	 */
	public static void saveSystemFiles(List<MultipartFile> files, String saveRoot) throws Exception {
		for (MultipartFile fi : files) {
			String name = fi.getOriginalFilename();
			String type = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
			String ppath = saveRoot + "/" + name;
			File file = new File(saveRoot);
			
			//修改当前文件下的文件名
			if(file.exists()) {
				if(file.listFiles() != null) {
					for (File f : file.listFiles()) {
						if(f.isFile()) {
							//只修改未修改过的 且 类型相同的文件
							if(f.getName().indexOf("_lastupdate_") == -1) {
								String fname = f.getName();
								String ftype = fname.substring(fname.lastIndexOf(".") + 1).toLowerCase();
								if(type.equals(ftype)) {
									StringBuffer sb = new StringBuffer(f.getPath());
									String newfilename = sb.insert(f.getPath().lastIndexOf("."), "_lastupdate_" + + new Date().getTime()).toString();
									f.renameTo(new File(newfilename));
								}
							}
						}
					}
				}
			}
			
			// 检查是否存在, 不存在则创建目录。
			if(!file.exists()) file.mkdirs();
			// 生成文件。
			fi.transferTo(new File(ppath));
		}
	}
	
	/**
	 * 下载文件
	 * @author Liangjing 2019年9月24日
	 * @param name 文件名称
	 * @param path 绝对路径
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public static void downloadFiles(String name, String path, HttpServletRequest request, HttpServletResponse response) throws Exception {
		OutputStream os = null;
		FileInputStream fis = null;
		
		try {
			//检测编码格式并编码文件名
			String charset = "UTF-8";
			String agent = request.getHeader("USER-AGENT");
			if (agent == null) name = URLEncoder.encode(name, charset);
			else {
				if (agent.indexOf("Firefox") != -1) {
					charset = "ISO-8859-1";
					name = new String(name.getBytes("UTF-8"), charset);
				} else if (agent.indexOf("Mozilla") != -1) {
					charset = "UTF-8";
					name = URLEncoder.encode(name, charset);
				} else name = URLEncoder.encode(name, charset);
			}
			
			//设置响应头
			response.reset();
			response.setContentType("application/octet-stream;charset=" + charset);
			response.setHeader("Content-Disposition", "attachment;filename=" + name);
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Pargam", "no-cache");
			
			//读取文件数据并写入响应流
			int read = -1;
			byte[] buffer = new byte[1024];
			os = response.getOutputStream();
			fis = new FileInputStream(path);
			while ((read = fis.read(buffer)) > 0) {
				os.write(buffer, 0, read);
			}
			os.flush();
			
		} finally {
			//关闭输入输出流
			if (fis != null) fis.close();
			if (os != null) os.close();
		}
	}
}
